const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`; // aa-aa 标签名
const qnameCapture = `((?:${ncname}\\:)?${ncname})`; // aa:aa
const startTagOpen = new RegExp(`^<${qnameCapture}`); // 标签开头的正则 捕获的内容是标签名

const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`); // 匹配标签结尾的 </div>
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/; // 匹配属性的
const startTagClose = /^\s*(\/?)>/; // 匹配标签结束的 >
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g;

export function parseHtml(html) {
  function createASTElement(tag, attrs) {
    // vue3支持多个根元素（外层加了一个空元素），vue2只有一个根节点
    return {
      tag,
      type: 1,
      children: [],
      attrs,
      parent: null,
    };
  }

  let root = null;
  let currentParent;
  let stack = [];
  // 根据开始结束文本内容生成ast语法树
  function start(tagName, attrs) {
    let element = createASTElement(tagName, attrs);
    if (!root) {
      root = element;
    }
    currentParent = element;
    stack.push(element);
  }
  // TODO: 234
  function end(tagName) {
    // span ==>  </span>
    // 记录父子元素关系

    // 为什么要移除？ 记录嵌套标签的父子关系
    let element = stack.pop();
    currentParent = stack[stack.length - 1];
    if (currentParent) {
      element.parent = currentParent;
      currentParent.children.push(element);
    }
  }

  function char(text) {
    text = text.replace(/\s/g, "");
    if (text) {
      currentParent.children.push({
        type: 3,
        text,
      });
    }
  }
  function advance(n) {
    html = html.substring(n);
  }

  function parseStartTag() {
    const start = html.match(startTagOpen);
    if (start) {
      // return start;
      let match = {
        tagName: start[1],
        attrs: [],
      };
      advance(start[0].length); // 获取元素,然后删除匹配过的元素
      // 查找属性
      let end;
      let attr;
      // 如果不是开头标签结尾，就一直解析
      while (
        !(end = html.match(startTagClose)) &&
        (attr = html.match(attribute))
      ) {
        advance(attr[0].length);
        match.attrs.push({
          name: attr[1],
          value: attr[3] || attr[4] || attr[5] || true,
        });
      }
      if (end) {
        advance(end[0].length);
        return match;
      }
    }
  }

  while (html) {
    let textEnd = html.indexOf("<");
    if (textEnd === 0) {
      let startTagMatch = parseStartTag();
      if (startTagMatch) {
        // console.log("开始" + startTagMatch.tagName);
        // 开始标签
        start(startTagMatch.tagName, startTagMatch.attrs);
        continue;
      }

      //结束标签
      let endTagMatch = html.match(endTag);
      if (endTagMatch) {
        //干掉结尾标签
        advance(endTagMatch[0].length);
        // console.log("结尾" + endTagMatch[1]);
        end(endTagMatch[1]);
        continue;
      }
    }
    let text;
    if (textEnd > 0) {
      //  开始解析文本
      text = html.substring(0, textEnd);
    }
    //
    if (text) {
      advance(text.length);
      char(text);
    }
  }

  return root;
}

/*
 *  ast语法树
 *
 */
// const a = {
//   tag: "div",
//   type: 1, nodeType
//   attrs: [
//     {
//       style: "color: red",
//     },
//   ],
//   children: [
//     {
//       tag: "span",
//       type: 1,
//       attrs: [],
//       children: "",
//       parent: "",
//     },
//   ],
//   parent: null,
// };
